package com.cloudkinto.common.utils;

import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.HttpClient;

import javax.crypto.Cipher;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.cloudkinto.common.utils.OkHttpUtils.getUnsafeOkHttpClient;

public class YahooUtils {
//    public static final String clientIdV1 = "dj00aiZpPU1wcG9yTlFBSlFQcSZzPWNvbnN1bWVyc2VjcmV0Jng9YzA-";
//    public static final String clientSecretV1 = "GBvs8lGmUPdhKsbniiuET3aRP048tOJGYzFie4kX";
//
//    public static final String clientIdV2 = "dj00aiZpPTR4TWV0WnBqT1dWTyZzPWNvbnN1bWVyc2VjcmV0Jng9NDI-";
//    public static final String clientSecretV2 = "0yJ9T5VBjxKPQDbL2RgL1YK645PBNHtsF7oEXNX4";


    public static String yahooDoGet(String serviceUrl, String accessToken, Map parametersMap) throws Exception {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", "Bearer " + accessToken);//验证 eBay 市场帐户删除/关闭通知实际上来自 eBay 时，Authorization = Bearer +accessToken
        headerMap.put("content-type", "application/json; charset=utf-8");
        if (parametersMap.size() > 0)
            serviceUrl = serviceUrl + "?" + AmazonUtil.sortParams(parametersMap);
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1081);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = getUnsafeOkHttpClient().newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = AmazonUtil.createSPHeader(headerMap);
        Request request = requestBuilder.url(serviceUrl).get().build();
        Response response = null;
        String body = "";
        response = builder.build().newCall(request).execute();
        body = response.body().string();
        return body;
    }

    public static String yahooDoGetV3(String serviceUrl, Map parametersMap) throws Exception {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("content-type", "application/json; charset=utf-8");
        if (parametersMap.size() > 0)
            serviceUrl = serviceUrl + "?" + AmazonUtil.sortParams(parametersMap);
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1081);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = getUnsafeOkHttpClient().newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = AmazonUtil.createSPHeader(headerMap);
        Request request = requestBuilder.url(serviceUrl).get().build();
        Response response = null;
        String body = "";
        response = builder.build().newCall(request).execute();
        body = response.body().string();
        return body;
    }


    public static String getBase64ESA(String clientId, String clientSecret) {
        byte[] pass = (clientId.trim() + ":" + clientSecret.trim()).getBytes(StandardCharsets.UTF_8);
        return "Basic " + Base64.getEncoder().encodeToString(pass);
    }


    public static final String clientId = "dj00aiZpPTR4TWV0WnBqT1dWTyZzPWNvbnN1bWVyc2VjcmV0Jng9NDI-";

    private static final String clientSecret = "0yJ9T5VBjxKPQDbL2RgL1YK645PBNHtsF7oEXNX4";
    /**
     * 获取刷新令牌
     *
     * @param serviceUrl
     * @param param
     * @return
     * @throws Exception
     */
    public static String yahooDoPostAuth(String serviceUrl, String sellerId, String publicKey, Integer signatureVersion, Map<String, String> param) {
        return yahooDoPost(serviceUrl, getBase64ESA(clientId, clientSecret), sellerId, publicKey, signatureVersion, "application/x-www-form-urlencoded", param);
    }


    public static String yahooDoPost(String serviceUrl, String accessToken, String sellerId, String publicKey, Integer signatureVersion, String param)  {
        return yahooDoPost(serviceUrl, "Bearer " + accessToken, sellerId, publicKey, signatureVersion, "application/xml", param);
    }


    public static String yahooDoPost(String serviceUrl, String authorization, String sellerId, String publicKey, Integer signatureVersion, String contentType, Map<String, String> param)  {
        Response response = yahooDoPostUtils(serviceUrl, authorization, sellerId, publicKey, signatureVersion, contentType, param);
        if (response == null || response.body() == null) {
            return null;
        }
        String body = "";
        try {
            body = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return body;
    }

    public static String yahooDoPost(String serviceUrl, String authorization, String sellerId, String publicKey, Integer signatureVersion, String contentType, String param) {
        Response response = yahooDoPostUtils(serviceUrl, authorization, sellerId, publicKey, signatureVersion, contentType, param);
        if (response == null || response.body() == null) {
            return null;
        }

        String body = null;
        try {
            body = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return body;
    }

    /**
     * 表单格式上传xxx-from
     *
     * @param serviceUrl
     * @param authorization
     * @param contentType
     * @param param
     * @return
     * @throws Exception
     */
    public static Response yahooDoPostUtils(String serviceUrl, String authorization, String sellerId, String publicKey, Integer signatureVersion, String contentType, Map<String, String> param) {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", authorization);//Authorization -> 生产：
        headerMap.put("Content-type", contentType); //获取客户端AccessToken 需要设置
        String signature = getSignature(sellerId, publicKey);
        if (StringUtils.isNotBlank(signature)) {
            headerMap.put("X-sws-signature", signature);
            headerMap.put("X-sws-signature-version", signatureVersion+"");
        }
        OkHttpClient client = getUnsafeOkHttpClient();
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1081);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = client.newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = AmazonUtil.createSPHeader(headerMap);

        FormBody.Builder formBodyBuilder = new FormBody.Builder();
        if (param != null && !param.isEmpty()) {
            for (String key : param.keySet()) {
                formBodyBuilder.add(key, param.get(key));
            }
        }
        Request request = requestBuilder.url(serviceUrl)
                .post(formBodyBuilder.build())
                .build();
        Response response = null;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

    /**
     * xml格式上传
     *
     * @param serviceUrl
     * @param authorization
     * @param contentType
     * @param param
     * @return
     * @throws Exception
     */
    public static Response yahooDoPostUtils(String serviceUrl, String authorization, String sellerId, String publicKey, Integer signatureVersion, String contentType, String param)  {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", authorization);//Authorization -> 生产：
        if (StringUtils.isNotBlank(contentType)) {
            headerMap.put("Content-type", contentType); //获取客户端AccessToken 需要设置
        }
        String signature = getSignature(sellerId, publicKey);
        if (StringUtils.isNotBlank(signature)) {
            headerMap.put("X-sws-signature", signature);
            headerMap.put("X-sws-signature-version", signatureVersion+"");
        }
        OkHttpClient client = getUnsafeOkHttpClient();
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1081);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = client.newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(true);
        Request.Builder requestBuilder = AmazonUtil.createSPHeader(headerMap);
        Request request = requestBuilder.url(serviceUrl)
                .post(RequestBody.create(Objects.requireNonNull(MediaType.parse(contentType)), param))
                .build();

        Response response = null;
        try {
            response = client.newCall(request).execute();
            String authorizeStatus = response.header("X-SWS-Authorize-Status");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

    public static String getSignature(String sellerId, String publicKeyPem) {
        if (StringUtils.isBlank(sellerId) || StringUtils.isBlank(publicKeyPem)) {
            return null;
        }
        try {
//            Path keyFilePath = Paths.get("./public.key");//ストアクリエイターPro上で発行した公開鍵のパス ( 例 Windowsの場合: C:\\Users\\store\\public.key )

            // 現在日時取得
            long unixTime = System.currentTimeMillis() / 1000L;
            // 認証情報作成(ストアアカウントとunixtimestampを:で結合する)
            byte[] authenticationValue = String.format("%s:%d", sellerId, unixTime).getBytes();
            // pem形式の公開鍵読み込み
            // pem形式からder形式に変換するにあたり、不要部分を削除
            publicKeyPem = publicKeyPem
                    .replace("-----BEGIN PUBLIC KEY-----\n", "")  // (Windowsの場合: \n -> \r\n)
                    .replace("-----END PUBLIC KEY-----", "")
                    .replace("\n", "");                           // (Windowsの場合: \n -> \r\n)
            // 公開鍵インスタンス生成
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyPem));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
            // 暗号化インスタンス生成
            Cipher encryptorWithPublicKey = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            encryptorWithPublicKey.init(Cipher.ENCRYPT_MODE, publicKey);

            // 認証情報の暗号化実行
            byte[] encryptedAuthenticationValue = encryptorWithPublicKey.doFinal(authenticationValue);

            // 認証情報のBase64エンコード実行
            byte[] encodedAuthenticationValue = Base64.getEncoder().encode(encryptedAuthenticationValue);
            return new String(encodedAuthenticationValue);
            // HTTP通信準備
        } catch (Exception exception) {
            // エラーが出た場合にエラー内容を表示
            exception.printStackTrace();
        }
        return null;
    }


}
